// --------------------------------------------------------------------------------------------------------------------
// <copyright file="Matrix4Test.cs" company="Microsoft Corporation">
// The MIT License (MIT)
// 
// Copyright (c) 2014, Microsoft Corporation
// 
// Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Test.Robotics.Numerics
{
    using System;
    using System.IO;
    using System.Runtime.Serialization;
    using System.Xml;
    using System.Xml.Serialization;

    using Microsoft.Robotics.Numerics;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    /// <summary>
    /// Unit tests for the Matrix3 class
    /// </summary>
    [TestClass]
    public class Matrix4Test
    {
        /// <summary>
        /// Test the Matrix4 value constructor
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4ValueConstructor()
        {
            Matrix4 matrix = new Matrix4(2.0);
            Assert.IsTrue(
                matrix[0, 0] == 2.0 && matrix[0, 1] == 2.0 && matrix[0, 2] == 2.0 && matrix[0, 3] == 2.0
                && matrix[1, 0] == 2.0 && matrix[1, 1] == 2.0 && matrix[1, 2] == 2.0 && matrix[1, 3] == 2.0
                && matrix[2, 0] == 2.0 && matrix[2, 1] == 2.0 && matrix[2, 2] == 2.0 && matrix[2, 3] == 2.0
                && matrix[3, 0] == 2.0 && matrix[3, 1] == 2.0 && matrix[3, 2] == 2.0 && matrix[3, 3] == 2.0, 
                "Matrix4 value constructor failed");
        }

        /// <summary>
        /// Test the Matrix4 Identity constructor
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4IdentityConstructor()
        {
            Matrix4 matrix = Matrix4.Identity();
            Assert.IsTrue(
                matrix[0, 0] == 1.0 && matrix[0, 1] == 0.0 && matrix[0, 2] == 0.0 && matrix[0, 3] == 0.0
                && matrix[1, 0] == 0.0 && matrix[1, 1] == 1.0 && matrix[1, 2] == 0.0 && matrix[1, 3] == 0.0
                && matrix[2, 0] == 0.0 && matrix[2, 1] == 0.0 && matrix[2, 2] == 1.0 && matrix[2, 3] == 0.0
                && matrix[3, 0] == 0.0 && matrix[3, 1] == 0.0 && matrix[3, 2] == 0.0 && matrix[3, 3] == 1.0, 
                "Matrix4 Identity constructor failed");
        }

        /// <summary>
        /// Test the Matrix4 copy constructor
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4CopyConstructor()
        {
            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 1.0;
            matrix[0, 1] = 2.0;
            matrix[0, 2] = 3.0;
            matrix[0, 3] = 4.0;
            matrix[1, 0] = 5.0;
            matrix[1, 1] = 6.0;
            matrix[1, 2] = 7.0;
            matrix[1, 3] = 8.0;
            matrix[2, 0] = 9.0;
            matrix[2, 1] = 10.0;
            matrix[2, 2] = 11.0;
            matrix[2, 3] = 12.0;
            matrix[3, 0] = 13.0;
            matrix[3, 1] = 14.0;
            matrix[3, 2] = 15.0;
            matrix[3, 3] = 16.0;

            Matrix4 m = new Matrix4(matrix);

            Assert.IsTrue(
                m[0, 0] == 1.0 && m[0, 1] == 2.0 && m[0, 2] == 3.0 && m[0, 3] == 4.0 && m[1, 0] == 5.0 && m[1, 1] == 6.0
                && m[1, 2] == 7.0 && m[1, 3] == 8.0 && m[2, 0] == 9.0 && m[2, 1] == 10.0 && m[2, 2] == 11.0
                && m[2, 3] == 12.0 && m[3, 0] == 13.0 && m[3, 1] == 14.0 && m[3, 2] == 15.0 && m[3, 3] == 16.0, 
                "Matrix4 copy constructor failed");
        }

        /// <summary>
        /// Verifies construction from a 2D  array
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4ConstructFrom2DArray()
        {
            double[,] m1 = new double[4, 4];
            double k = 0.0;

            for (int i = 0; i < 4; ++i)
            {
                k += 10.0;

                for (int j = 0; j < 4; ++j)
                {
                    m1[i, j] = k + j;
                }
            }

            Matrix4 m2 = new Matrix4(m1);

            for (int i = 0; i < 4; ++i)
            {
                for (int j = 0; j < 4; ++j)
                {
                    Assert.AreEqual(m2[i, j], m1[i, j]);
                }
            }
        }

        /// <summary>
        /// Serialization / Deserialization
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4Serialize()
        {
            Matrix4 m1 = new Matrix4();
            double k = 0.0;

            for (int i = 0; i < 4; ++i)
            {
                k += 10.0;

                for (int j = 0; j < 4; ++j)
                {
                    m1[i, j] = k + j;
                }
            }

            using (MemoryStream sr = new MemoryStream(2048))
            {
                DataContractSerializer ds = new DataContractSerializer(typeof(Matrix4));

                XmlWriter xw = XmlWriter.Create(sr);
                ds.WriteObject(xw, m1);
                xw.Flush();

                sr.Position = 0;

                XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(sr, new XmlDictionaryReaderQuotas());
                Matrix4 m2 = (Matrix4)ds.ReadObject(reader, true);
                Assert.IsTrue(m1 == m2, "Serialization round trip failed");
            }
        }

        /// <summary>
        /// Test the Matrix4 transpose method
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4TransposeMethod()
        {
            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 1.0;
            matrix[0, 1] = 2.0;
            matrix[0, 2] = 3.0;
            matrix[0, 3] = 4.0;
            matrix[1, 0] = 5.0;
            matrix[1, 1] = 6.0;
            matrix[1, 2] = 7.0;
            matrix[1, 3] = 8.0;
            matrix[2, 0] = 9.0;
            matrix[2, 1] = 10.0;
            matrix[2, 2] = 11.0;
            matrix[2, 3] = 12.0;
            matrix[3, 0] = 13.0;
            matrix[3, 1] = 14.0;
            matrix[3, 2] = 15.0;
            matrix[3, 3] = 16.0;

            Matrix4 m = Matrix4.Transpose(matrix);

            Assert.IsTrue(
                m[0, 0] == 1.0 && m[0, 1] == 5.0 && m[0, 2] == 9.0 && m[0, 3] == 13.0 && m[1, 0] == 2.0
                && m[1, 1] == 6.0 && m[1, 2] == 10.0 && m[1, 3] == 14.0 && m[2, 0] == 3.0 && m[2, 1] == 7.0
                && m[2, 2] == 11.0 && m[2, 3] == 15.0 && m[3, 0] == 4.0 && m[3, 1] == 8.0 && m[3, 2] == 12.0
                && m[3, 3] == 16.0, 
                "Matrix4 transpose method failed");
        }

        /// <summary>
        /// Test the Matrix4 null transpose method
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4TransposeNullMethod()
        {
            Assert.IsNull(Matrix4.Transpose(null), "Matrix tranpose test failed");
        }

        /// <summary>
        /// Test the Matrix4 constant multiply
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4ConstantMultiply()
        {
            Matrix4 matrix = new Matrix4(2.0);

            Matrix4 m = 4.0 * matrix;

            Assert.IsTrue(
                m[0, 0] == 8.0 && m[0, 1] == 8.0 && m[0, 2] == 8.0 && m[0, 3] == 8.0 && m[1, 0] == 8.0 && m[1, 1] == 8.0
                && m[1, 2] == 8.0 && m[1, 3] == 8.0 && m[2, 0] == 8.0 && m[2, 1] == 8.0 && m[2, 2] == 8.0
                && m[2, 3] == 8.0 && m[3, 0] == 8.0 && m[3, 1] == 8.0 && m[3, 2] == 8.0 && m[3, 3] == 8.0, 
                "Matrix4 Constant multiply failed");
        }

        /// <summary>
        /// Matrix4 equals test
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4Equals()
        {
            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 1.0;
            matrix[0, 1] = 2.0;
            matrix[0, 2] = 3.0;
            matrix[0, 3] = 4.0;
            matrix[1, 0] = 5.0;
            matrix[1, 1] = 6.0;
            matrix[1, 2] = 7.0;
            matrix[1, 3] = 8.0;
            matrix[2, 0] = 9.0;
            matrix[2, 1] = 10.0;
            matrix[2, 2] = 11.0;
            matrix[2, 3] = 12.0;
            matrix[3, 0] = 13.0;
            matrix[3, 1] = 14.0;
            matrix[3, 2] = 15.0;
            matrix[3, 3] = 16.0;

            Matrix4 matrix2 = new Matrix4();
            matrix2[0, 0] = 1.0;
            matrix2[0, 1] = 2.0;
            matrix2[0, 2] = 3.0;
            matrix2[0, 3] = 4.0;
            matrix2[1, 0] = 5.0;
            matrix2[1, 1] = 6.0;
            matrix2[1, 2] = 7.0;
            matrix2[1, 3] = 8.0;
            matrix2[2, 0] = 9.0;
            matrix2[2, 1] = 10.0;
            matrix2[2, 2] = 11.0;
            matrix2[2, 3] = 12.0;
            matrix2[3, 0] = 13.0;
            matrix2[3, 1] = 14.0;
            matrix2[3, 2] = 15.0;
            matrix2[3, 3] = 16.0;

            Assert.IsTrue(matrix == matrix2, "Matrix4 Equals test failed");
            Assert.IsTrue(matrix.Equals(matrix2), "Matrix4 Equals test failed");
        }

        /// <summary>
        /// Matrix4 subtraction test
        /// </summary>
        [Priority(0)]
        [TestCategory("Unit")]
        public void Matrix4Subtraction()
        {
            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 1.0;
            matrix[0, 1] = 2.0;
            matrix[0, 2] = 3.0;
            matrix[0, 3] = 4.0;
            matrix[1, 0] = 5.0;
            matrix[1, 1] = 6.0;
            matrix[1, 2] = 7.0;
            matrix[1, 3] = 8.0;
            matrix[2, 0] = 9.0;
            matrix[2, 1] = 10.0;
            matrix[2, 2] = 11.0;
            matrix[2, 3] = 12.0;
            matrix[3, 0] = 13.0;
            matrix[3, 1] = 14.0;
            matrix[3, 2] = 15.0;
            matrix[3, 3] = 16.0;

            Matrix4 matrix2 = new Matrix4();
            matrix2[0, 0] = 1.0;
            matrix2[0, 1] = 2.0;
            matrix2[0, 2] = 3.0;
            matrix2[0, 3] = 4.0;
            matrix2[1, 0] = 5.0;
            matrix2[1, 1] = 6.0;
            matrix2[1, 2] = 7.0;
            matrix2[1, 3] = 8.0;
            matrix2[2, 0] = 9.0;
            matrix2[2, 1] = 10.0;
            matrix2[2, 2] = 11.0;
            matrix2[2, 3] = 12.0;
            matrix2[3, 0] = 13.0;
            matrix2[3, 1] = 14.0;
            matrix2[3, 2] = 15.0;
            matrix2[3, 3] = 16.0;

            Matrix4 result = matrix - matrix2;

            Assert.IsTrue(
                Math.Abs(result[0, 0]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[0, 1]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[0, 2]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[0, 3]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[1, 0]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[1, 1]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[1, 2]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[1, 3]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[2, 0]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[2, 1]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[2, 2]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[2, 3]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[3, 0]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[3, 1]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[3, 2]) < MathConstants.ErrorEpsilon
                && Math.Abs(result[3, 3]) < MathConstants.ErrorEpsilon, 
                "Matrix4 subtraction operator failed");
        }

         /// <summary>
        /// Matrix4 subtraction test
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
        [TestCategory("Unit")]
        public void Matrix4NullSubtraction()
        {
            Matrix4 matrix = new Matrix4(0);

            // this should throw
            Matrix4 matrix2 = matrix - null; 
        }

        /// <summary>
        /// Matrix4 inverse test
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4Inverse()
        {
            Matrix4 foo = Matrix4.Identity();

            Random rnd = new Random();
            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = rnd.NextDouble() * 10.0;
            matrix[0, 1] = rnd.NextDouble() * 10.0;
            matrix[0, 2] = rnd.NextDouble() * 10.0;
            matrix[0, 3] = rnd.NextDouble() * 10.0;
            matrix[1, 0] = rnd.NextDouble() * 10.0;
            matrix[1, 1] = rnd.NextDouble() * 10.0;
            matrix[1, 2] = rnd.NextDouble() * 10.0;
            matrix[1, 3] = rnd.NextDouble() * 10.0;
            matrix[2, 0] = rnd.NextDouble() * 10.0;
            matrix[2, 1] = rnd.NextDouble() * 10.0;
            matrix[2, 2] = rnd.NextDouble() * 10.0;
            matrix[2, 3] = rnd.NextDouble() * 10.0;
            matrix[3, 0] = rnd.NextDouble() * 10.0;
            matrix[3, 1] = rnd.NextDouble() * 10.0;
            matrix[3, 2] = rnd.NextDouble() * 10.0;
            matrix[3, 3] = rnd.NextDouble() * 10.0;

            Matrix4 matrix2 = Matrix4.Inverse(matrix);
            Matrix4 ident = Matrix4.Identity();
            Matrix4 result = (matrix * matrix2) - ident;
            Matrix4 zero = new Matrix4(0.0);

            Assert.IsTrue(result == zero, "Matrix Inverse test failed" + result.ToString());
        }

        /// <summary>
        /// A version of the Matrix4Inverse test that should fail if MathConstants.ErrorEpsilon 
        /// is ~ 10^-13 or less.
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4InversePrecisionErrorRegression()
        {
            Matrix4 foo = Matrix4.Identity();

            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 3.60297317784418;
            matrix[0, 1] = 8.6965825169797;
            matrix[0, 2] = 1.53690523539526;
            matrix[0, 3] = 2.45786755925876;
            matrix[1, 0] = 4.81947733313752;
            matrix[1, 1] = 6.0103022288579;
            matrix[1, 2] = 8.87119858007468;
            matrix[1, 3] = 4.17794575177969;
            matrix[2, 0] = 5.68041317429413;
            matrix[2, 1] = 0.518517657424564;
            matrix[2, 2] = 2.93417756116678;
            matrix[2, 3] = 8.74559662712067;
            matrix[3, 0] = 7.63891361543858;
            matrix[3, 1] = 7.35912104479928;
            matrix[3, 2] = 2.89738870360767;
            matrix[3, 3] = 9.44905799787913;

            Matrix4 matrix2 = Matrix4.Inverse(matrix);
            Matrix4 ident = Matrix4.Identity();
            Matrix4 result = (matrix * matrix2) - ident;
            Matrix4 zero = new Matrix4(0.0);

            Assert.IsTrue(result == zero, "Matrix Inverse test failed" + result.ToString());
        }

        /// <summary>
        /// Matrix4 ToString test 
        /// </summary>
        [Priority(0)]
        [TestMethod]
        [TestCategory("Unit")]
        public void Matrix4ToStringTest()
        {
            Matrix4 foo = Matrix4.Identity();

            Matrix4 matrix = new Matrix4();
            matrix[0, 0] = 1;
            matrix[0, 1] = 0;
            matrix[0, 2] = 0;
            matrix[0, 3] = 0;
            matrix[1, 0] = 0;
            matrix[1, 1] = 1;
            matrix[1, 2] = 0;
            matrix[1, 3] = 0;
            matrix[2, 0] = 0;
            matrix[2, 1] = 0;
            matrix[2, 2] = 1;
            matrix[2, 3] = 0;
            matrix[3, 0] = 0;
            matrix[3, 1] = 0;
            matrix[3, 2] = 0;
            matrix[3, 3] = 1;

            string matrixString = matrix.ToString();

            Assert.AreEqual(matrixString, "1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1", "Matrix ToString test failed");
        }

        /// <summary>
        /// Matrix4 Addition test 
        /// </summary>
        [Priority(0)]
        [TestCategory("Unit")]
        public void Matrix4AdditionTest()
        {
            Matrix4 matrix = new Matrix4(0);
            Matrix4 matrix2 = new Matrix4(0);
            Matrix4 matrix3 = new Matrix4();

            matrix[0, 0] = 1;
            matrix[0, 1] = 2;
            matrix[0, 2] = 3;
            matrix[0, 3] = 4;
            matrix[1, 0] = 5;
            matrix[1, 1] = 6;
            matrix[1, 2] = 7;
            matrix[1, 3] = 8;
            matrix[2, 0] = 9;
            matrix[2, 1] = 10;
            matrix[2, 2] = 11;
            matrix[2, 3] = 12;
            matrix[3, 0] = 13;
            matrix[3, 1] = 14;
            matrix[3, 2] = 15;
            matrix[3, 3] = 16;

            matrix2[0, 0] = 1;
            matrix2[0, 1] = 2;
            matrix2[0, 2] = 3;
            matrix2[0, 3] = 4;
            matrix2[1, 0] = 5;
            matrix2[1, 1] = 6;
            matrix2[1, 2] = 7;
            matrix2[1, 3] = 8;
            matrix2[2, 0] = 9;
            matrix2[2, 1] = -8;
            matrix2[2, 2] = -7;
            matrix2[2, 3] = -6;
            matrix2[3, 0] = -5;
            matrix2[3, 1] = -4;
            matrix2[3, 2] = -3;
            matrix2[3, 3] = -2;

            matrix3 = matrix2 + matrix;

            Assert.IsTrue(  
                            matrix3[0, 0] == 2 
                            && matrix3[0, 1] == 4 
                            && matrix3[0, 2] == 6 
                            && matrix3[0, 3] == 8 
                            && matrix3[1, 0] == 10 
                            && matrix3[1, 1] == 12 
                            && matrix3[1, 2] == 14 
                            && matrix3[1, 3] == 16 
                            && matrix3[2, 0] == 18 
                            && matrix3[2, 1] == 2 
                            && matrix3[2, 2] == 4 
                            && matrix3[2, 3] == 6 
                            && matrix3[3, 0] == 8 
                            && matrix3[3, 1] == 10 
                            && matrix3[3, 2] == 12
                            && matrix3[3, 3] == 14, 
                            "Matrix Addition test failed");
        }

         /// <summary>
        /// Matrix4 Addition test 
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
        [TestCategory("Unit")]
        public void Matrix4NullAdditionTest()
        {
            Matrix4 matrix = new Matrix4(0);

            // this should throw
            Matrix4 matrix2 = matrix + null; 
        }

        /// <summary>
        /// Matrix4 Multiplication test 
        /// </summary>
        [Priority(0)]
        [TestCategory("Unit")]
        public void Matrix4MultiplicationTest()
        {
            Matrix4 matrix = new Matrix4(0);
            Matrix4 matrix2 = new Matrix4(0);
     
            matrix[0, 0] = 1;
            matrix[0, 1] = 2;
            matrix[0, 2] = 3;
            matrix[0, 3] = 4;
            matrix[1, 0] = 5;
            matrix[1, 1] = 6;
            matrix[1, 2] = 7;
            matrix[1, 3] = 8;
            matrix[2, 0] = 9;
            matrix[2, 1] = 8;
            matrix[2, 2] = 7;
            matrix[2, 3] = 6;
            matrix[3, 0] = 5;
            matrix[3, 1] = 4;
            matrix[3, 2] = 3;
            matrix[3, 3] = 2;

            matrix2[0, 0] = 1;
            matrix2[0, 1] = 0;
            matrix2[0, 2] = 0;
            matrix2[0, 3] = 0;
            matrix2[1, 0] = 0;
            matrix2[1, 1] = 1;
            matrix2[1, 2] = 0;
            matrix2[1, 3] = 0;
            matrix2[2, 0] = 0;
            matrix2[2, 1] = 0;
            matrix2[2, 2] = 1;
            matrix2[2, 3] = 0;
            matrix2[3, 0] = 0;
            matrix2[3, 1] = 0;
            matrix2[3, 2] = 0;
            matrix2[3, 3] = 1;

            Matrix4 matrix3 = matrix2 * matrix;

            Assert.IsTrue(
                            matrix3[0, 0] == 1
                            && matrix3[0, 1] == 2
                            && matrix3[0, 2] == 3
                            && matrix3[0, 3] == 4
                            && matrix3[1, 0] == 5
                            && matrix3[1, 1] == 6
                            && matrix3[1, 2] == 7
                            && matrix3[1, 3] == 8
                            && matrix3[2, 0] == 9
                            && matrix3[2, 1] == 8
                            && matrix3[2, 2] == 7
                            && matrix3[2, 3] == 6
                            && matrix3[3, 0] == 5
                            && matrix3[3, 1] == 4
                            && matrix3[3, 2] == 3
                            && matrix3[3, 3] == 2,
                            "Matrix Multiplication test failed");            
        }

        /// <summary>
        /// Matrix4 Multiplication test 
        /// </summary>
        [Priority(0)]
        [TestCategory("Unit")]
        public void Matrix4MultiplicationNullTest1()
        {
            Matrix4 matrix = null;
            matrix = null;
            Matrix4 matrix3 = 5 * matrix;
            Assert.IsTrue(matrix3 == null, "Matrix Multiplication test failed");
        }

        /// <summary>
        /// Matrix4 Multiplication test 
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
        [TestCategory("Unit")]
        public void Matrix4MultiplicationNullTest2()
        {
            Matrix4 matrix = new Matrix4(0);

            // this should throw
            Matrix4 matrix2 = matrix * null; 
        }

        /// <summary>
        /// Matrix4 Out of bounds test 
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
        [TestCategory("Unit")]
        public void Matrix4OutofBoundsTest1()
        {
            Matrix4 matrix = new Matrix4(0);

            // this should throw
            matrix[-1, -1] = 0; 
        }

        /// <summary>
        /// Matrix4 Out of bounds test 
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentOutOfRangeException))]
        [TestCategory("Unit")]
        public void Matrix4OutofBoundsTest2()
        {
            Matrix4 matrix = new Matrix4(0);
            double val = matrix[100, 100]; ////this should throw
        }

        /// <summary>
        /// Matrix4 Null Copy Constructor Test
        /// </summary>
        [Priority(0)]
        [TestMethod, ExpectedException(typeof(ArgumentNullException))]
        [TestCategory("Unit")]
        public void NullCopyConstructorTest()
        {
            Matrix4 nullCopyConstructor = null;
            Matrix4 matrix = new Matrix4(nullCopyConstructor); ////this should throw
        }
    }
}
